/**
 * @file      jsonconfig.h
 * @copyright Copyright (c) 2019, CYG-ZCW Co., Ltd. All Rights Reserved.
 * @brief     brief
 * @author    caiwang213@qq.com
 * @date      2019-06-19 13:38:20
 *
 * @note
 *  jsonconfig.h defines
 */
#ifndef __JSONCONFIG_H__
#define __JSONCONFIG_H__
#include <QJsonObject>
#include <QJsonArray>
#include <QVector>
#include <QFile>
#include <QJsonDocument>
#include <QMutex>

template<class T>
class JsonConfig
{
public:
    JsonConfig(const QString &jfile);

public:
    int                load();

    QVector<T>&        configs();
    int                add(const T &obj);
    int                del(const T &obj);
    int                mod(const T &o, T &n);

protected:
    int                save();

private:
    QString            _jfile;

    QVector<T>         _configs;
    QMutex             _mutex;
};

template<class T>
JsonConfig<T>::JsonConfig(const QString &jfile)
{
    _jfile = jfile;
}

template<class T>
QVector<T>& JsonConfig<T>::configs()
{
    return _configs;
}

template<class T>
int JsonConfig<T>::add(const T &obj)
{
    QMutexLocker locker(&_mutex);
    _configs.push_back(obj);

    return save();
}

template<class T>
int JsonConfig<T>::del(const T &obj)
{
    QMutexLocker locker(&_mutex);
    /* QVector<T>::iterator i = std::find(_configs.begin(), _configs.end(), obj); */
    auto i = std::find(_configs.begin(), _configs.end(), obj);
    if (i == _configs.end())
    {
        return -1;
    }
    _configs.erase(i);

    return save();
}

template<class T>
int JsonConfig<T>::mod(const T &o, T &n)
{
    QMutexLocker locker(&_mutex);
    /* QVector<T>::iterator i = std::find(_configs.begin(), _configs.end(), o); */
    auto i = std::find(_configs.begin(), _configs.end(), o);
    if (i == _configs.end())
    {
        return -1;
    }

    *i = n;

    return save();
}

template<class T>
int JsonConfig<T>::save()
{
    QJsonArray jarray;
    for (int i = 0; i < _configs.size(); ++ i)
    {
        jarray.append(_configs[i]);
    }

    QJsonDocument document;
    document.setArray(jarray);

    QByteArray jsonStr = document.toJson();

    QFile file(_jfile);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        std::string errStr = file.errorString().toStdString();
        return -1;
    }

    qint64 res = file.write(jsonStr);
    if (res < 0)
    {
        std::string errStr = file.errorString().toStdString();
        file.close();
        return -1;
    }
    file.close();

    return 0;
}

template<class T>
int JsonConfig<T>::load()
{
    QMutexLocker locker(&_mutex);

    QFile jfile(_jfile);
    if (!jfile.open(QIODevice::ReadOnly))
    {
        std::string errStr = jfile.errorString().toStdString();
        return -1;
    }

    QByteArray bytes = jfile.readAll();
    jfile.close();

    QJsonParseError jerr;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(bytes, &jerr);
    if (jerr.error != QJsonParseError::NoError)
    {
        return -1;
    }

    if (jsonDoc.isEmpty() || jsonDoc.isNull())
    {
        return -1;
    }

    if (!jsonDoc.isArray())
    {
        return -1;
    }

    QJsonArray jarray = jsonDoc.array();

    _configs.clear();
    for (int i = 0; i < (int)jarray.size(); ++i)
    {
        _configs.push_back(jarray[i].toObject());
    }

    return 0;
}

#endif
